﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using yaTDL.Core;
using yaTDL.Core.IO;

namespace yaTDL.Testing
{
    class Program
    {
        static ToodledoClientTester toodledoTester = new ToodledoClientTester();

        [STAThread] // for OLE
        static void Main(string[] args)
        {
            Console.WriteLine("yaTDL.Testing");
            waitforcommand();


        }

        static string[] cmd;

        private static void waitforcommand()
        {
            Console.WriteLine();

            string input = Console.ReadLine();

            char[] separators = { Char.Parse("#") };
            cmd = input.Split(separators, StringSplitOptions.RemoveEmptyEntries);

            if (!cmd.Any()) { waitforcommand(); }

            switch (cmd[0])
            {
                case "getchanges_test":

                    Console.WriteLine("True: " + TaskStore.GetChanges().Where(x => x.HandledInSync == true).Count().ToString());        
                    Console.WriteLine("False: " + TaskStore.GetChanges().Where(x => x.HandledInSync == false).Count().ToString());        


                    break;


                case "/?": printAvaiableCommands();
                    break;

                case "recurrence.getnextdate": recurrence_getnextdate();
                    break;

                case "recurrence.isequal": recurrence_isequal();
                    break;

                case "recurrence.parsedate": recurrence_parsedate();
                    break;

                case "rec.gnd": recurrence_getnextdate();
                    break;

                case "rec.ieq": recurrence_isequal();
                    break;

                case "rec.pd": recurrence_parsedate();
                    break;

                case "cls": cls();
                    break;

                case "exporttoxml": exportToXml();
                    break;

                case "readfromxml": readFromXml();
                    break;

                case "sync": sync();
                    break;

                case "cleantodoist": cleanTodoist();
                    break;

                case "listprojects": listProjects();
                    break;

                case "comparedatafiles": compareDataFiles();
                    break;

                case " all":
                    toodledoTester.testAll();
                    break;
            }

            if (cmd[0].StartsWith("test"))
            {
                if (cmd[0].Substring(5).StartsWith("recurrence"))
                {
                    testRecurrence();
                }
                else if (cmd[0].Substring(5).StartsWith("toodledo"))
                {
                    toodledoTester.EnterCommand(cmd[0].Replace("test toodledo ", ""));
                }

            }
            else
            {
                unknownCommand();
            }

            waitforcommand();

        }

        private static void printAvaiableCommands()
        {
            Console.WriteLine();
            Console.WriteLine("------------------------------------\n");
            Console.WriteLine("AVAILABLE COMMANDS");
            Console.WriteLine();
            Console.WriteLine("recurrence.getnextdate#DATESTRING#LASTDATE (=rec.gnd#DATESTRING#LASTDATE)");
            Console.WriteLine("Displays the next possible date after LASTDATE that matches the value of DATESTRING.");
            Console.WriteLine();
            Console.WriteLine("recurrence.isequal#VALUE (=rec.ieq#VALUE)");
            Console.WriteLine("Checks whether VALUE is a equal number or not.");
            Console.WriteLine();
            Console.WriteLine("recurrence.parsedate#STRING (=rec.pd#STRING)");
            Console.WriteLine("Tries to parse STRING into a DateTime.");
            Console.WriteLine();
            Console.WriteLine("readfromxml#FILENAME");
            Console.WriteLine("Will try to read the indicated XML-File and convert it to a Collection<Project> (will not display any results in the console window)");
            Console.WriteLine();
            Console.WriteLine("exporttoxml#FILENAME");
            Console.WriteLine("Will export all Projects currently stored in TaskStore to the indicated XML-File.");
            Console.WriteLine();
            Console.WriteLine("cls");
            Console.WriteLine("Clears the screen");
            Console.WriteLine("------------------------------------");
            Console.WriteLine();
            waitforcommand();

        }

        static void cls()
        {
            Console.Clear();
            waitforcommand();
        }

        static void recurrence_getnextdate()
        {
            if (cmd.Length != 3) { unknownCommand(); }
            else
            {

                Recurrence rec = new Recurrence();

                DateTime lastDate;
                if (cmd[2] == "now") lastDate = DateTime.Now;
                else lastDate = DateTime.Parse(cmd[2]);

                Console.WriteLine("recurrence.getnextdate(" + cmd[1] + ", " + cmd[2] + ") --> " + Recurrence.GetNextDate(lastDate, 50, cmd[1]));
                waitforcommand();
            }

        }

        static void recurrence_isequal()
        {
            //if (cmd.Length != 2) { unknownCommand(); }
            //else
            //{
            //    int value;
            //    if (Int32.TryParse(cmd[1], out value))
            //    {
            //        Console.WriteLine("recurrence.isequal(" + value.ToString() + ") --> " + Recurrence.isEqual(value).ToString());
            //    }
            //    else { Console.WriteLine("INVALID VALUE"); }
            //}
            //waitforcommand();
        }

        static void recurrence_parsedate()
        {
        }

        static XMLFileHandler xmlaccess = new XMLFileHandler();

        static void exportToXml()
        {
            if (cmd.Length != 2) { unknownCommand(); }
            else
            {
                xmlaccess.SaveData(TaskStore.GetProjects(), TaskStore.GetTasks(), TaskStore.GetChanges(), cmd[1]);
            }
            waitforcommand();
        }

        static void readFromXml()
        {
            if (cmd.Length != 2) { unknownCommand(); }
            else
            {
                Collection<Project> projects = xmlaccess.GetProjects(cmd[1]);
                Collection<Task> tasks = xmlaccess.GetTasks(cmd[1]);
                Collection<yaTDL.Core.Change> changes = xmlaccess.GetChanges(cmd[1]);
            }
            waitforcommand();
        }

        static void compareDataFiles()
        {
            //if (cmd.Length != 3) { unknownCommand(); }
            //else 
            //{
            //    XMLFileaccess fileaccess = new XMLFileaccess();
            //    Collection<Project> originalData = cmd[1] == "taskstore" ? TaskStore.GetProjects(): fileaccess.GetProjects(cmd[1]);
            //    Collection<Project> newData = cmd[2] == "taskstore" ? TaskStore.GetProjects() : fileaccess.GetProjects(cmd[2]);

            //    TodoistSyncService syncservice = new TodoistSyncService();
            //    syncservice.GetChanges(originalData, newData);
            //    waitforcommand();
            //}
        }

        static void sync()
        {
            //if (cmd.Length != 3) { unknownCommand(); }
            //else 
            //{
            //    SyncService syncService = new SyncService();
            //    TodoistClient todoistClient = new TodoistClient();
            //    string token = todoistClient.Login(cmd[1], cmd[2]).APIToken;
            //    syncService.Token = token;

            //    syncService.StartSync();
            //    Console.WriteLine("Sync completed");
            //    waitforcommand();
            //}
        }

        static void cleanTodoist()
        {
            //if (cmd.Length != 3) { unknownCommand(); }
            //else
            //{                
            //    TodoistClient todoistClient = new TodoistClient();
            //    string token = todoistClient.Login(cmd[1], cmd[2]).APIToken;

            //    Collection<Project> projects = todoistClient.GetProjects(token);

            //    foreach (Project p in projects)
            //    {
            //        todoistClient.DeleteProject(token, p.Id);        
            //    }

            //    Console.WriteLine("Todoist cleaned up");
            //    waitforcommand();
            //}
        }

        static void exportTodoist()
        {
            //if (cmd.Length != 4) { return; }

            //SyncService syncService = new SyncService();
            //TodoistClient todoistClient = new TodoistClient();
            //string token = todoistClient.Login(cmd[2], cmd[3]).APIToken;
            //syncService.Token = token;

            //Collection<Project> project = syncService.TodoistGetProjectsAndTasks();

            //xmlaccess.SaveProjects(project, cmd[1]);
        }

        static void testRecurrence()
        {
            Recurrence rec = new Recurrence();

            DateTime startDate = DateTime.Parse("01.01.2010");



            testRecurrence_test(startDate, DateTime.Parse("01.01.2010"), 0);
            testRecurrence_test(startDate, DateTime.Parse("08.01.2010"), 1);
            testRecurrence_test(startDate, DateTime.Parse("01.02.2010"), 2);
            testRecurrence_test(startDate, DateTime.Parse("01.01.2011"), 3);
            testRecurrence_test(startDate, DateTime.Parse("02.01.2010"), 4);
            testRecurrence_test(startDate, DateTime.Parse("15.01.2010"), 5);
            testRecurrence_test(startDate, DateTime.Parse("01.03.2010"), 6);
            testRecurrence_test(startDate, DateTime.Parse("01.07.2010"), 7);
            testRecurrence_test(startDate, DateTime.Parse("01.04.2010"), 8);

            testRecurrence_test(startDate, startDate.AddDays(0), 100);
            testRecurrence_test(startDate, DateTime.Now.AddDays(7), 101);
            testRecurrence_test(startDate, DateTime.Now.AddMonths(1), 102);
            testRecurrence_test(startDate, DateTime.Now.AddYears(1), 103);
            testRecurrence_test(startDate, DateTime.Now.AddDays(1), 104);
            testRecurrence_test(startDate, DateTime.Now.AddDays(14), 105);
            testRecurrence_test(startDate, DateTime.Now.AddMonths(2), 106);
            testRecurrence_test(startDate, DateTime.Now.AddMonths(6), 107);
            testRecurrence_test(startDate, DateTime.Now.AddMonths(3), 108);

            testRecurrence_test(startDate, DateTime.Parse("04.01.2010"), 50, "every 3 days");
            testRecurrence_test(startDate, DateTime.Parse("22.01.2010"), 50, "every 3 weeks");
            testRecurrence_test(startDate, DateTime.Parse("01.04.2010"), 50, "every 3 months");
            testRecurrence_test(startDate, DateTime.Parse("01.01.2013"), 50, "every 3 years");

            testRecurrence_test(startDate, DateTime.Parse("18.01.2010"), 50, "on the third monday of each month");
            testRecurrence_test(startDate, DateTime.Parse("11.01.2010"), 50, "on the second monday of each month");
            testRecurrence_test(startDate, DateTime.Parse("05.02.2010"), 50, "on the 1 friday of each month");
            testRecurrence_test(startDate, DateTime.Parse("13.01.2010"), 50, "on the 2 wed of each month");

            testRecurrence_test(startDate, DateTime.Parse("04.01.2010"), 50, "every mon");
            testRecurrence_test(startDate, DateTime.Parse("02.01.2010"), 50, "every weekend");
            testRecurrence_test(DateTime.Parse("02.01.2010"), DateTime.Parse("03.01.2010"), 50, "every weekend");
            testRecurrence_test(startDate, DateTime.Parse("04.01.2010"), 50, "every weekday");
            testRecurrence_test(DateTime.Parse("04.01.2010"), DateTime.Parse("05.01.2010"), 50, "every weekday");

            testRecurrence_test(startDate, DateTime.Now.AddDays(3), 150, "every 3 days");
            testRecurrence_test(startDate, DateTime.Now.AddDays(21), 150, "every 3 weeks");
            testRecurrence_test(startDate, DateTime.Now.AddMonths(3), 150, "every 3 months");
            testRecurrence_test(startDate, DateTime.Now.AddYears(12), 150, "every 12 years");


            waitforcommand();


        }

        static Recurrence recurrence = new Recurrence();

        static void testRecurrence_test(DateTime original, DateTime expected, int repeat, string advancedrepeat = "")
        {
            DateTime calculated = Recurrence.GetNextDate(original, repeat, advancedrepeat);

            if (calculated == expected)
            {
                Console.WriteLine(String.Format("OK repeat={0}, datestring={1}", repeat, advancedrepeat));
            }
            else
            {
                //due to the way the test is written calculated and expected differ by a minimal amount of time, so as long as the date is correct, it can be ignored;
                if (calculated.Date == expected.Date)
                    Console.WriteLine(String.Format("OK repeat={0}, datestring={1}", repeat, advancedrepeat));
                else
                    Console.WriteLine(String.Format("FAILED repeat={0}, datestring={1};    expected={2}, calculated={3}", repeat, advancedrepeat, expected, calculated));
            }

        }

        static void listProjects()
        {
            foreach (Project p in TaskStore.GetProjects())
            {
                Console.WriteLine(p.ToString());
                Console.WriteLine();

            }
            waitforcommand();

        }

        public static void unknownCommand()
        {
            Console.WriteLine();
            Console.WriteLine("INVALID COMMAND");
            Console.WriteLine();
            waitforcommand();
        }
    }
}
